﻿package igz.fleaxy.ui.form.textarea 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFieldType;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import flash.utils.Timer;
	import igz.fleaxy.Fleaxy;
	import igz.fleaxy.css.CssManager;
	import igz.fleaxy.io.MouseManager;
	import igz.fleaxy.ui.text.LabelUi;
	import igz.fleaxy.ui.text.TextUi;
	import igz.fleaxy.ui.scrollbar.ScrollBarV;
	import igz.fleaxy.ui.scrollbar.ScrollContainerUi;
	import igz.fleaxy.util.ObjectUtil;
	
	/**
	 * Clase encargada de generar un TextArea, es decir, una caja de texto grande multilinea
	 * 
	 * @author Intelygenz | www.intelygenz.com
	 */
	public class TextAreaUi extends Sprite {
		
		protected var _Settings : Object = {  "width" : 100
											, "height" : 100
											, "bgColor" : 0xFFFFFF
											, "bgAlpha" : 1
											, "label" : ""
											, "labelStyle" : ""
											, "textStyle" : ""
											, "scrollBgStyle" : ""
											, "scrollMarkStyle" : ""
											, "labelMargin" : 4 // Margen entre la etiqueta y la caja de texto
											, "example" : "" // Texto que aparece a modo de ejemplo
											, "css" : null
											, "scrollAlwaysVisible" : true
										   };
		
		private var _Name  : String;
		
		private var _Label			 : LabelUi;
		protected var _TextUi			 : TextUi;
		
		protected var _ScrollV		 : ScrollBarV;
		
		public function get $ScrollV () : ScrollBarV {
			return _ScrollV;
		}
		
		protected var _ScrollContainer : ScrollContainerUi;
		
		private var _TimerScrollPosition : Timer;

		/**
		 * Caja de Texto con barra de scroll vertical
		 * 
		 * @param	p_name Nombre usado para realizar el envio
		 * @param	p_settings{ width: 100
		 *						, height: 100
		 *						, bgColor: 0xFFFFFF
		 *						, bgAlpha: 1
		 *						, bgBorder: 0x000000
		 *						, label: ""
		 *						, labelStyle: ""
		 *						, textStyle: ""
		 *						, scrollBgStyle: ""
		  *						, scrollMarkStyle: ""
		 *						, labelMargin: 4 // Margen entre la etiqueta y la caja de texto
		 * 						, example: "" // Texto que aparece a modo de ejemplo
		 * 						, css: null
		 *					};
		 * @example
		 * 
		 */
		public function TextAreaUi(p_name:String, p_style:String = "", p_settings:Object = null) {
			
			if ( p_style != "" ) {
				var bgColor:Object = Fleaxy.$Current.$CssManager.$GetStyleValue(p_style, CssManager.$STYLE_BACKGROUND, _Settings.css);
				if ( bgColor != null ) {
					_Settings.bgColor = (bgColor as String).replace("#", "0x");
				}
				var bgAlpha:Object =  Fleaxy.$Current.$CssManager.$GetStyleValue(p_style, CssManager.$STYLE_ALPHA, _Settings.css);
				if ( bgAlpha != null ) {
					_Settings.bgAlpha = bgAlpha;
				}
			}
			ObjectUtil.$Merge( p_settings, _Settings, false );

			if ( _Settings["label"] != "" ) {
				_Label = new LabelUi(_Settings["label"], _Settings["labelStyle"], { "fixWidth": _Settings["width"], "maxLines": 1 });
				this.addChild(_Label);
			}
			_ScrollContainer = new ScrollContainerUi( { "border":_Settings["bgBorder"],"background":_Settings["bgColor"], "backgroundAlpha":_Settings["bgAlpha"] } );
			_ScrollContainer.addEventListener( MouseEvent.CLICK, _ScrollContainer_OnClick );
			this.addChild( _ScrollContainer );
			
			_TextUi = new TextUi("", _Settings["textStyle"]);
			_TextUi.wordWrap = true;
			_TextUi.multiline = true;
			_TextUi.selectable = true;
			_TextUi.type = TextFieldType.INPUT;
			_TextUi.autoSize = TextFieldAutoSize.LEFT;
			_TextUi.htmlText = _Settings.example;
			_TextUi.addEventListener(KeyboardEvent.KEY_DOWN, _OnTextUi_KeyDown);
			_TextUi.addEventListener(KeyboardEvent.KEY_UP, _OnTextUi_KeyUp);
			_TextUi.addEventListener(FocusEvent.FOCUS_IN, _OnTextUi_FocusIn);
			_TextUi.addEventListener(FocusEvent.FOCUS_OUT, _OnTextUi_FocusOut);
			_ScrollContainer.addChild( _TextUi );
			_ScrollV = new ScrollBarV(_ScrollContainer, { "backgroundStyle": _Settings["scrollBgStyle"], "markStyle": _Settings["scrollMarkStyle"] }, {"alwaysVisible":_Settings["scrollAlwaysVisible"]} );
			addChild( _ScrollV );

			_TimerScrollPosition = new Timer(20);
			_TimerScrollPosition.addEventListener( TimerEvent.TIMER, _OnTimerSetScrollPosition );

			MouseManager.$SetCursorToDisplayObject( _ScrollContainer, MouseCursor.IBEAM );

			_Refresh();
		}

		protected function _ScrollContainer_OnClick(p_mouseEvent:MouseEvent):void {
			this.stage.focus = _TextUi;
		}

		private function _OnTextUi_FocusIn(p_focusEvent:FocusEvent):void {
			if ( _Settings.example != "" && _TextUi.text == _Settings.example ) {
				_TextUi.text = "";
			}
		}
		
		private function _OnTextUi_FocusOut(p_focusEvent:FocusEvent):void {
			if ( _Settings.example != "" && _TextUi.text == "" ) {
				_TextUi.text = _Settings.example;
			}
		}
		
		private function _OnTextUi_KeyDown(p_keyEvent:KeyboardEvent):void {
			if ( !_TimerScrollPosition.running ) {
				_TimerScrollPosition.start();
			}
		}
		
		private function _OnTextUi_KeyUp(p_keyEvent:KeyboardEvent):void {
			_TimerScrollPosition.stop();
		}
		
		private function _OnTimerSetScrollPosition (p_timerEvent:TimerEvent) : void {
			_SetScrollPosition();
		}
		
		/**
		 * Realiza scroll vertical si la posición de inserción de texto supera la altura del contenedor
		 */
		private function _SetScrollPosition():void {
			if ( _TextUi.text != "" && _TextUi.getCharBoundaries(0) != null ) {
				var numLine:Number = _TextUi.getLineIndexOfChar( _TextUi.caretIndex ) + 1;
				if ( numLine == 0 ) {
					// Si es una nueva linea sin retorno de carro getLineIndexOfChar devuelve -1
					numLine = _TextUi.numLines;
				}
				var insertPointHeight:Number = _TextUi.getCharBoundaries(0).height * numLine;

				if ( insertPointHeight > _ScrollContainer.height ) {
					_ScrollContainer.$Container.y = _ScrollContainer.height - insertPointHeight;
				}
				else {
					_ScrollContainer.$Container.y = 0;
				}
			}
			_ScrollContainer.dispatchEvent( new Event(Event.CHANGE) );
		}
		
		
		/**
		 * Actualiza el tamaño de la caja de texto con otros parámetros teniendo en cuenta el contenido
		 */
		private function _Refresh() : void {
			_TextUi.width   = _Settings["width"];
			_ScrollContainer.width = _Settings["width"];
			
			if ( _Label != null ) {
				var textHeight:uint = _Settings["height"] - _Label.height - _Settings["labelMargin"];
				_ScrollContainer.y = _Label.y + _Label.height + _Settings["labelMargin"];
				_ScrollContainer.height = textHeight;
				_TextUi.height = textHeight;
			}
			else {
				_TextUi.height = _Settings["height"];
				_ScrollContainer.height = _Settings["height"];
			}
			
		}
		
		override public function set width(p_width:Number) : void {
			if ( p_width != _Settings.width ) {
				_Settings["width"] = p_width;
				_Refresh();
			}
		}
		
		override public function set height(p_height:Number) : void {
			if ( p_height != _Settings.height ) {
				_Settings["height"] = p_height;
				_Refresh();
			}
		}
		
		public function $Clear():void {
			if ( _Settings.example != "" ) {
				_TextUi.text = _Settings["example"];
			}
			else {
				_TextUi.text = "";
			}
			_ScrollContainer.dispatchEvent( new Event(Event.CHANGE) );
		}
		
		/**
		 * Valor del campo
		 */
		public function get $Value() : String {
			var value:String = _TextUi.text;
			if ( _Settings["example"] != "" && value == _Settings["example"] ) {
				value = "";
			}
			return value;
		}
		
		public function set $Value( p_value:String ) : void {
			_TextUi.text = p_value;
			_ScrollContainer.dispatchEvent( new Event(Event.CHANGE) );
		}
		
		/**
		 * Etiqueta
		 */
		public function get $LabelUi() : LabelUi {
			return _Label;
		}
		
		/**
		 * Cuadro de texto
		 */
		public function get $TextUi() : TextUi {
			return _TextUi;
		}
		
	}
}